package cn.zzq.aix.nativeinterface.javareflector;

import java.lang.reflect.Type;
import java.util.HashMap;

import com.google.appinventor.components.runtime.collect.Maps;

import gnu.lists.FString;

public class ClassManager {
	// 当前JavaReflector的类加载器，java环境使用系统类加载器，
	public static ClassLoader classLoader = null;
	// 当类开始加载时，是否需要初始化
	public static boolean initializeOnClassLoaded = true;

	/**
	 * 类型映射表，建立文本->类对象的映射
	 */
	private HashMap<String, Class<?>> typeNameMap = Maps.newHashMap();

	public boolean containsClass(Class<?> class_) {
		return typeNameMap.containsValue(class_);
	}

	public boolean containsName(String name) {
		return typeNameMap.containsKey(name);
	}

	private void put(String classSimpleName, Class<?> class_) {
		typeNameMap.put(classSimpleName, class_);
		Logger.log("ClassManager.put", class_);
	}

	/**
	 * 通过名称获取一个Type/Class对象 该名称可以是 
	 * 1.已经导入的class对象 (java.lang.*下的所有类，以及调用ImportClass导入后的class对象的类名简称与自定义的名称)</br>
	 * 2.基本数据类型int,byte,boolean,short,long,double,float,void</br>
	 * 3.数组数据类型，使用int[],byte[]，Object[]等创建表示一维数组的类，使用int[][],byte[][],Object[][]等创建表示二维数组的类，以此类推</br>
	 * 
	 * @param name
	 *            类名，类简称，自定义名称，基本数据类型名，数组名
	 * 
	 * 
	 * @return 类型对象
	 * @throws ClassNotFoundException
	 */
	public Class<?> get(String name) throws ClassNotFoundException {
		Logger.log("ClassManager.get<String>", "尝试获取类型", name);
		if (typeNameMap.containsKey(name)) {
			Class<?> class_ = typeNameMap.get(name);
			Logger.log("ClassManager.get<String>", "从类管理器中获取到类型", class_);
			return class_;
		} else if (name.contains("[]")) {
			// 是数组类型
			String[] strings = name.split("(\\[).*?(\\])", 257);
			Type elementType = get(strings[0]);		//正则表达式分割数组，第0项为数组元素类型
			int dimension = strings.length - 1;		//正则表达式分割数组，后面有几个[]，就表示几维数组
			Class<?> type = ArrayUtil.buildArrayType(elementType, dimension);
			typeNameMap.put(name, (Class<?>) type);
			Logger.log("ClassManager.get<String>", "获取到类型", type);
			return type;
		} else {
			Logger.log("ClassManager.get<String>", "尝试从类加载器", classLoader, "获取类名为", name, "的类型");
			Class<?> class_=Class.forName(name, initializeOnClassLoaded, classLoader);
			Logger.log("ClassManager.get<String>", "获取到了类型",class_);
			return class_;
		}
	}

	// 单例模式，将自身实例化对象设置为一个属性，并用static修饰
	private volatile static ClassManager instance = null;

	// 单例模式，构造函数私有化
	private ClassManager() {
		// 默认debug开关是关闭的，而启用debug模式是在JavaReflector对象实例化之后。
		// 所以在静态代码块中将提前打开以便于输出静态代码块中的日志。
		// debug开关将在静态代码块结束之后还原为关闭模式
		Logger.debugMode = true;
		// 在这里先设置当前的ClassLoader为系统类加载器。
		// 以便于在Java测试环境中运行通过
		// 在Android环境下将使用Activity的类加载器
		if (!Util.isAndroidEnvironment()) {
			classLoader = ClassLoader.getSystemClassLoader();
		}
		
		
		Logger.log("ClassManager", "开始导入默认类");
		// 导入基本数据类型类
		put("int", int.class);
		put("short", short.class);
		put("long", long.class);
		put("boolean", boolean.class);
		put("byte", byte.class);
		put("char", char.class);
		put("float", float.class);
		put("double", double.class);
		put("void", void.class);
		// 默认导入java.lang.*中的部分常用类型
		importClass("java.lang.Short");
		importClass("java.lang.Object");
		importClass("java.lang.Character");
		importClass("java.lang.Number");
		importClass("java.lang.Integer");
		importClass("java.lang.Double");
		importClass("java.lang.Class");
		importClass("java.lang.Byte");
		importClass("java.lang.Long");
		importClass("java.lang.Character");
		importClass("java.lang.Void");
		importClass("java.lang.Float");
		importClass("java.lang.String");
		importClass("java.lang.Boolean");
		importClass("java.lang.CharSequence");
		importClass("java.lang.Thread");
		importClass("java.lang.StringBuffer");
		importClass("java.lang.Math");
		importClass("java.lang.ClassLoader");
		importClass("java.lang.ThreadGroup");
		importClass("java.lang.ThreadLocal");
		importClass("java.lang.StringBuilder");
		importClass("java.lang.System");
		importClass("java.lang.Runnable");
		importClass("java.lang.Iterable");
		importClass("java.lang.Runtime");
		importClass("java.lang.Enum");
		importClass("java.lang.ThreadDeath");
		Logger.log("ClassManager", "默认类型导入完毕");
		Logger.debugMode = false;
	}

	public void importClass(Class<?> class_) {
		if (class_ == null) {
			throw new ReflectException(class_, "ClassManager.importClass<Class>", "类不能为空");
		} else {
			importClassAs(class_,class_.getSimpleName());
			Logger.log("ClassManager.importClass<Class>", "成功导入类", class_);
		}
	}

	public void importClass(String className) {
		try {
			Class<?> class_=get(className);
			importClassAs(class_,class_.getSimpleName());
			Logger.log("ClassManager.importClass<Class>", "成功导入类", class_);
		} catch (ClassNotFoundException e) {
			throw new ReflectException(className,"ClassManager.importClass<String>","导入类失败");
		}
		
	}

	public void importClassAs(String className, String classSimpleName) {
		Class<?> class_ = parseAsClass(className);
		importClassAs(class_, classSimpleName);
		Logger.log("ClassManager.importClassAs<String,String>", "成功导入类", class_);

	}

	public void importClassAs(Class<?> class_, String name) {
		// 如果导入简称相同，而要导入不同的类，那么将触发一个RefletException
		if (typeNameMap.containsKey(name) && !typeNameMap.get(name).getName().equals(class_.getName())) {
			StringBuffer sb = new StringBuffer();
			sb.append("导入异常，导入类的名称:\n");
			sb.append(name);
			sb.append("你想要导入类:\n");
			sb.append(class_);
			sb.append("所属类加载器:\n");
			sb.append(class_.getClassLoader());
			sb.append("已存在导入类:\n");
			sb.append(typeNameMap.get(name));
			sb.append("所属类加载器:\n");
			sb.append(typeNameMap.get(name).getClassLoader());
			throw new ReflectException(name, "ClassManager.importClassAs<Class,String>", sb);
		} else {
			// 一切正常，正常导入
			typeNameMap.put(name, (Class<?>) class_);
			Logger.log("ClassManager.importClassAs<Class,String>", "成功导入类", class_, "并重命名", name);
		}
	}

	/**
	 * 1.传入一个类，将直接返回这个类对象<br/>
	 * 2.传入一个文本，将根据文本解析出对应的类对象 <br/>
	 * 3.传入一个对象，将获取表示该对象的类的类对象 <br/>
	 * 
	 * @param noc
	 * @return
	 */
	public Class<?> parseAsClass(Object noc) {
		if (noc instanceof Class<?>) {
			return (Class<?>) noc;
		} else if (noc instanceof String || noc instanceof FString) {
			try {
				// 解析成class对象
				noc = getClassManager().get(noc.toString());
				return parseAsClass(noc);
			} catch (ClassNotFoundException e) {
				throw new ReflectException(noc, "ClassManager.toClass<Object>", e);
			}
		} else if (noc != null) {
			// 直接返回表示这个对象的类
			return noc.getClass();
		} else {
			return null;
		}
	}

	public static ClassManager getClassManager() {
		// 第一次检查是否实例化，如果没有进入if
		if (instance == null) {
			synchronized (ClassManager.class) {
				// 由某个线程成功取得了类的锁，实例化对象前再次检查instance是否被实例化
				if (instance == null) {
					instance = new ClassManager();
				}
			}
		}
		return instance;
	}
}
